/*
 * These files are distributed under the terms of the GNU GPLv2, the GNU General
 * Public version 2. See LICENSE.txt
 */
package fileCommodore.plugin;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.prefs.*;

import javax.swing.*;

import org.apache.commons.vfs.*;

import fileCommodore.*;

/**
 * @author nado18@gmail.com, on Jul 26, 2007
 */
public abstract class Plugin
{
	public abstract void handle( KeyEvent ev );
	
	public abstract void activeSelectionChanged();
	
	public abstract void inactiveSelectionChanged();
	
	private Selection activeSelection;
	private Selection inactiveSelection;
	
	private static Main frame;
	
	public static void setController( Main m )
	{
		frame = m;
	}
	
	public Main getController()
	{
		return frame;
	}
	
	public void setActiveSelection( Selection selection )
	{
		activeSelection = selection;
	}
	
	public void setInactiveSelection( Selection selection )
	{
		inactiveSelection = selection;
	}
	
	public Selection getActiveSelection()
	{
		return activeSelection;
	}
	
	public Selection getInactiveSelection()
	{
		return inactiveSelection;
	}
	
	private String getKey( String key )
	{
		String retval =
				String.format( "plugin-%s-%s", getClass().getName(), key );
		
		return retval;
	}
	
	public String getProperty( String key, String defaultValue )
	{
		Preferences p = Preferences.userNodeForPackage( Main.class );
		String pluginKey = getKey( key );
		String retval = p.get( pluginKey, defaultValue );
		return retval;
	}
	
	public String getProperty( String key )
	{
		return getProperty( key, "" );
	}
	
	public void setProperty( String key, String value )
	{
		Preferences p = Preferences.userNodeForPackage( Main.class );
		String pluginKey = getKey( key );
		p.put( pluginKey, value );
	}
	
	public void log( Exception ex )
	{
		
	}
	
	protected Component getDialogParent()
	{
		return frame;
	}
	
	public void report( String msg, Exception ex )
	{
		String pluginName = getClass().getName();
		
		showError( String.format(
			"There was an error in the '%s' plugin.\r\n\r\n%s\r\n\r\n%s",
			pluginName,
			msg,
			ex ), String.format( "Error in '%s' plugin.", pluginName ) );
	}
	
	private static boolean isMac()
	{
		return System.getProperty( "os.name" ).toLowerCase().contains( "mac" );
	}
	
	private static boolean isWindows()
	{
		return System.getProperty( "os.name" ).toLowerCase().contains(
			"windows" );
	}
	
	private static boolean isUnix()
	{
		return !( isMac() || isWindows() );
	}
	
	public boolean isAltDown( KeyEvent ev )
	{
		boolean retval =
				( isMac() && ev.isMetaDown() ) || ( !isMac() && ev.isAltDown() );
		
		return retval;
	}
	
	public boolean isCtrlDown( KeyEvent ev )
	{
		boolean retval = ev.isControlDown();
		
		return retval;
	}
	
	private static Process launch( File workingDirectory, Collection<String> command )
			throws IOException
	{
		// Read the OS' environment variables
		Vector<String> vEnv = new Vector<String>();
		Map<String, String> mEnv = System.getenv();
		String[] env = new String[] {};
		for (String key : mEnv.keySet())
		{
			String value = mEnv.get( key );
			vEnv.add( String.format( "%s=%s", key, value ) );
		}
		env = vEnv.toArray( env );
		
		String[] sCmd = new String[] {};
		sCmd = command.toArray( sCmd );
		
		Process p = Runtime.getRuntime().exec( sCmd, env, workingDirectory );
		return p;
	}
	
	public static Process launchProcessWithoutTerminal( File workingDirectory,
		String[] command ) throws IOException
	{
		Vector<String> vCmd = new Vector<String>();
		vCmd.add( "cmd" );
		vCmd.add( "/c" );
		vCmd.add( "start" );
		
		for (String arg : command)
		{
			vCmd.add( arg );
		}
		
		Process p = launch( workingDirectory, vCmd );
		return p;
	}
	
	public Process launchProcessWithTerminal( File workingDirectory,
		String[] command, boolean keepOpen ) throws IOException
	{
		String toggle = keepOpen ? "/k" : "/c";
		
		Vector<String> vCmd = new Vector<String>();
		vCmd.add( "cmd" );
		vCmd.add( "/c" );
		vCmd.add( "start" );
		vCmd.add( "cmd" );
		vCmd.add( toggle );
		
		for (String arg : command)
		{
			vCmd.add( arg );
		}
		
		Process p = launch( workingDirectory, vCmd );
		return p;
	}
	
	public Process launchTerminal( File workingDirectory ) throws IOException
	{
		Vector<String> vCmd = new Vector<String>();
		vCmd.add( "cmd" );
		vCmd.add( "/c" );
		vCmd.add( "start" );
		vCmd.add( "cmd" );
		
		Process p = launch( workingDirectory, vCmd );
		return p;
	}
	
	public void showError( String title, String message )
	{
		show( title, message, JOptionPane.ERROR_MESSAGE );
	}
	
	public void showError( String title, String message, Exception ex )
	{
		String msg = String.format( "%s\r\n\r\n%s", message, ex );
		showError( title, msg );
	}
	
	public void showWarning( String title, String message )
	{
		show( title, message, JOptionPane.WARNING_MESSAGE );
	}
	
	private void show( String title, String message, int messageType )
	{
		JOptionPane.showMessageDialog(
			getDialogParent(),
			message,
			title,
			messageType );
	}
	
	public void changeActiveTo( FileObject fo ) throws FileSystemException
	{
		frame.changeActiveTo( fo );
	}
	
	public void changeActiveTo( String path ) throws FileSystemException
	{
		FileObject fo = resolve( path );
		changeActiveTo( fo );
	}
	
	public void changeInactiveTo( FileObject fo ) throws FileSystemException
	{
		frame.changeInactiveTo( fo );
	}
	
	public void changeInactiveTo( String path ) throws FileSystemException
	{
		FileObject fo = resolve( path );
		changeInactiveTo( fo );
	}
	
	private FileObject resolve( String path ) throws FileSystemException
	{
		FileObject retval = frame.resolve( path );
		return retval;
	}
	
	public File toFile( FileObject fo )
	// TODO: Compare with FileRowItem.toFile
	{
		String sUri = fo.getName().getPath();
		File retval = new File( sUri );
		return retval;
	}
	
	public String ask( String title, String message )
	{
		String retval =
				JOptionPane.showInputDialog(
					frame,
					message,
					title,
					JOptionPane.QUESTION_MESSAGE );
		return retval;
	}
	
}
